/*
 * PhotonRTOS础光实时操作系统 -- 锁
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef __ASM_SMP_LOCK_H
#define __ASM_SMP_LOCK_H

#include <photon/compiler.h>
#include <asm/processor.h>
#include <asm/barrier.h>

#define TICKET_SHIFT	16

struct arch_smp_lock_t {
	uint32_t lock;
} __attribute__((aligned(4)));

#define __ARCH_SMP_LOCK_UNLOCKED {0}

#define ARCH_FUN_arch_smp_lock_value_unlocked_DEFINED
static inline int arch_smp_lock_value_unlocked(struct arch_smp_lock_t *lock)
{
	return lock->lock == 0;
}

#define ARCH_FUN_arch_smp_lock_is_locked_p_DEFINED
static inline int arch_smp_lock_is_locked(struct arch_smp_lock_t *lock)
{
	return !arch_smp_lock_value_unlocked(lock);
}

#define ARCH_FUN_arch_smp_lock_DEFINED
static inline void arch_smp_lock(struct arch_smp_lock_t *lock)
{
    boolean         retVal;
    volatile uint32 spinLockVal;

    retVal = FALSE;

    do
    {
        spinLockVal = 1UL;
        spinLockVal =
            (uint32)__cmpAndSwap(((unsigned int *)&lock->lock), spinLockVal, 0);

        /* Check if the SpinLock WAS set before the attempt to acquire spinlock */
        if (spinLockVal == 0)
        {
            retVal = TRUE;
        }
    } while ((retVal == FALSE));
}

#define ARCH_FUN_arch_smp_trylock_DEFINED
static inline int arch_smp_trylock(struct arch_smp_lock_t *lock)
{
    volatile uint32 spinLockVal;

	spinLockVal = 1UL;
	spinLockVal =
		(uint32)__cmpAndSwap(((unsigned int *)&lock->lock), spinLockVal, 0);

	return spinLockVal == 0;
}

#define ARCH_FUN_arch_smp_unlock_DEFINED
static inline void arch_smp_unlock(struct arch_smp_lock_t *lock)
{
	smp_mb();
	lock->lock = 0;
}

#endif /* __ASM_SMP_LOCK_H */
